#include "stdafx.h"
#include "FileCategory.h"  // 包含自定义头文件
#include <algorithm>       // 包含算法库（用于transform等）
#include <map>             // 包含map容器

// 实现：从文件名中提取扩展名
std::wstring FileCategory::GetFileExtension(const std::wstring& filename) {
    size_t dotPos = filename.find_last_of(L".");  // 查找最后一个点号的位置
    if (dotPos != std::wstring::npos && dotPos < filename.length() - 1) {  // 如果找到点号且不在末尾
        return filename.substr(dotPos + 1);  // 返回点号后的子字符串（扩展名）
    }
    return L"";  // 没有扩展名返回空字符串
}

// 实现：将字符串转换为小写
std::wstring FileCategory::ToLower(const std::wstring& str) {
    std::wstring result = str;  // 创建字符串副本
    std::transform(result.begin(), result.end(), result.begin(), ::towlower);  // 使用transform转换为小写
    return result;  // 返回转换后的字符串
}

// 实现：检查扩展名是否属于文档类型
bool FileCategory::IsDocument(const std::wstring& ext) {
    // 定义文档类型的扩展名列表
    static const std::vector<std::wstring> docExtensions = {
        L"pdf", L"doc", L"docx", L"txt", L"rtf", L"xls", L"xlsx",
        L"ppt", L"pptx", L"odt", L"ods", L"odp", L"pages", L"numbers"
    };
    // 在列表中查找扩展名，找到返回true，否则返回false
    return std::find(docExtensions.begin(), docExtensions.end(), ext) != docExtensions.end();
}

// 实现：检查扩展名是否属于图片类型
bool FileCategory::IsImage(const std::wstring& ext) {
    // 定义图片类型的扩展名列表
    static const std::vector<std::wstring> imgExtensions = {
        L"jpg", L"jpeg", L"png", L"gif", L"bmp", L"ico", L"svg",
        L"webp", L"tiff", L"tif", L"psd", L"ai", L"eps"
    };
    // 在列表中查找扩展名
    return std::find(imgExtensions.begin(), imgExtensions.end(), ext) != imgExtensions.end();
}

// 实现：检查扩展名是否属于视频类型
bool FileCategory::IsVideo(const std::wstring& ext) {
    // 定义视频类型的扩展名列表
    static const std::vector<std::wstring> videoExtensions = {
        L"mp4", L"avi", L"mkv", L"mov", L"wmv", L"flv", L"mpeg",
        L"mpg", L"m4v", L"3gp", L"webm", L"vob"
    };
    // 在列表中查找扩展名
    return std::find(videoExtensions.begin(), videoExtensions.end(), ext) != videoExtensions.end();
}

// 实现：检查扩展名是否属于音频类型
bool FileCategory::IsAudio(const std::wstring& ext) {
    // 定义音频类型的扩展名列表
    static const std::vector<std::wstring> audioExtensions = {
        L"mp3", L"wav", L"flac", L"aac", L"ogg", L"wma", L"m4a",
        L"aiff", L"aif", L"mid", L"midi"
    };
    // 在列表中查找扩展名
    return std::find(audioExtensions.begin(), audioExtensions.end(), ext) != audioExtensions.end();
}

// 实现：检查扩展名是否属于压缩文件类型
bool FileCategory::IsArchive(const std::wstring& ext) {
    // 定义压缩文件类型的扩展名列表
    static const std::vector<std::wstring> archiveExtensions = {
        L"zip", L"rar", L"7z", L"tar", L"gz", L"bz2", L"xz",
        L"iso", L"cab", L"jar", L"war"
    };
    // 在列表中查找扩展名
    return std::find(archiveExtensions.begin(), archiveExtensions.end(), ext) != archiveExtensions.end();
}

// 实现：检查扩展名是否属于可执行文件类型
bool FileCategory::IsExecutable(const std::wstring& ext) {
    // 定义可执行文件类型的扩展名列表
    static const std::vector<std::wstring> exeExtensions = {
        L"exe", L"msi", L"bat", L"cmd", L"com", L"scr", L"ps1"
    };
    // 在列表中查找扩展名
    return std::find(exeExtensions.begin(), exeExtensions.end(), ext) != exeExtensions.end();
}

// 实现：根据文件名获取文件分类
std::wstring FileCategory::GetFileCategory(const std::wstring& filename) {
    std::wstring ext = ToLower(GetFileExtension(filename));  // 获取小写的扩展名

    if (ext.empty()) return L"其他";  // 如果扩展名为空，返回"其他"分类
    if (IsDocument(ext)) return L"文档";  // 检查是否为文档类型
    if (IsImage(ext)) return L"图片";     // 检查是否为图片类型
    if (IsVideo(ext)) return L"视频";     // 检查是否为视频类型
    if (IsAudio(ext)) return L"音频";     // 检查是否为音频类型
    if (IsArchive(ext)) return L"压缩文件";  // 检查是否为压缩文件类型
    if (IsExecutable(ext)) return L"应用程序";  // 检查是否为可执行文件类型

    return L"其他";  // 都不匹配则返回"其他"分类
}

// 实现：将文件列表按分类分组
std::map<std::wstring, std::vector<std::wstring>> FileCategory::CategorizeFiles(
    const std::vector<std::wstring>& files) {

    std::map<std::wstring, std::vector<std::wstring>> categories;  // 创建分类映射

    for (const auto& file : files) {  // 遍历所有文件
        std::wstring category = GetFileCategory(file);  // 获取文件分类
        categories[category].push_back(file);  // 将文件添加到对应分类的向量中
    }

    return categories;  // 返回分类结果
}